package lumis.portal.crypto;


import java.security.MessageDigest;

import lumis.portal.PortalException;
import lumis.util.XmlUtil;

import org.w3c.dom.Node;

/**
 * Uses a MessageDigest algorithm to encrypt data.
 * <p>
 * In this cipher's configuration, the value of <code>algorithm</code> element 
 * is used to specify the MessageDigest algorithm; and the <code>provider</code>
 * element may optionally be used to specify the MessageDigest provider.
 * @see MessageDigest
 * @version $Revision: 11180 $ $Date: 2009-12-04 18:13:02 -0200 (Fri, 04 Dec 2009) $
 * @since 5.5.0
 */
public class MessageDigestCipher extends AbstractCipher
{
	private String algorithm = "SHA-512";
	private String provider = null;
	
	@Override
	protected boolean getUseURLSafeBase64Variant()
	{
		// this MessageDigestCipher does not use the safe URL Base64 variant
		// to keep backward compatibility.
		return false;
	}

	/** 
	 * Returns the message digest algorithm to be used.
	 * @return the algorithm.
	 * @since 5.5.0 
	 */
	protected String getAlgorithm()
	{
		return algorithm;
	}

	/**
	 * Sets the message digest algorithm to be used.
	 * @param algorithm the algorithm.
	 * @since 5.5.0
	 */
	protected void setAlgorithm(String algorithm)
	{
		this.algorithm = algorithm;
	}

	/**
	 * Returns the message digest provider to be used.
	 * @return the provider, or <code>null</code> if the default provider 
	 * search is to be used.
	 * @since 5.5.0
	 */
	protected String getProvider()
	{
		return provider;
	}

	/**
	 * Sets the message digest provider to be used.
	 * @param provider the provider, or <code>null</code> if the default provider
	 * search is to be used.
	 * @since 5.5.0
	 */
	protected void setProvider(String provider)
	{
		this.provider = provider;
	}

	public void init(Node configuration) throws PortalException
	{
		if (configuration != null)
		{
			setAlgorithm(XmlUtil.readNodeString("algorithm", configuration, getAlgorithm()));
			setProvider(XmlUtil.readNodeString("provider", configuration));
		}
	}
	
	/**
	 * Returns a new {@link MessageDigest} instance based on this cipher's
	 * {@link #getAlgorithm()} and {@link #getProvider()}.
	 * @return the message digest.
	 * @see MessageDigest#getInstance(String, String)
	 * @since 5.5.0
	 */
	protected MessageDigest createMessageDigest()
	{
		try
		{
			if (getProvider() == null)
				return MessageDigest.getInstance(getAlgorithm());
			else
				return MessageDigest.getInstance(getAlgorithm(), getProvider());
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}
	
	public byte[] encrypt(byte[] value)
	{
		if (value == null)
			throw new IllegalArgumentException("value to be encrypted cannot be null");

		MessageDigest md = createMessageDigest();
		return md.digest(value);
	}
	
	public byte[] decrypt(byte[] value)
	{
		throw new UnsupportedOperationException("This cipher does not support decryption");
	}
}
